package com.gange.filter;

import com.gange.constants.RedisPrefix;
import com.gange.exception.IllTokenException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;
@Component
public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenGatewayFilterFactory.Config> {
    public TokenGatewayFilterFactory() {
        super(Config.class);
    }
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public GatewayFilter apply(TokenGatewayFilterFactory.Config config) {
        //在这个方法里面拦截请求和放行请求
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                //判断配置项token是否为true
                if(config.requiredToken) {
                    //1.判断路径中是否有token参数
                    String token = exchange.getRequest().getQueryParams().getFirst("token");
                    if(StringUtils.isEmpty(token)){
                        throw new IllTokenException("没有权限");
                    }
                    //2.获取到token后看redis里面是否有token
                    if(!redisTemplate.hasKey(RedisPrefix.TOKEN_KEY+token)){
                        throw new IllTokenException("redis里面没有token信息");
                    }
                }
                //放行请求
                return chain.filter(exchange);
            }
        };
    }

    //用来配置将使用filter时指定值赋值给Config中哪个属性
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("requiredToken");
    }

    public static class Config {
        private boolean requiredToken;
        public Config() {
        }

        public boolean isRequiredToken() {
            return requiredToken;
        }

        public void setRequiredToken(boolean requiredToken) {
            this.requiredToken = requiredToken;
        }
    }
}
